/**
 * time_helper.js
 * 时间处理助手，提供日期时间格式化和计算功能
 */

// 尝试导入dayjs
let dayjsLib;
try {
  dayjsLib = require('dayjs');
} catch (e) {
  console.warn('加载dayjs失败，使用内置时间处理函数');
  dayjsLib = null;
}

/**
 * 格式化日期为指定格式
 * @param {Date|number|string} date - 日期对象、时间戳或日期字符串
 * @param {string} format - 格式化模板，如 'YYYY-MM-DD HH:mm:ss'
 * @return {string} 格式化后的日期字符串
 */
function formatDate(date, format = 'YYYY-MM-DD') {
  if (!date) return '';
  
  // 如果有dayjs，优先使用
  if (dayjsLib) {
    return dayjsLib(date).format(format);
  }
  
  // 转换为Date对象
  const d = typeof date === 'object' ? date : new Date(date);
  
  const year = d.getFullYear();
  const month = (d.getMonth() + 1).toString().padStart(2, '0');
  const day = d.getDate().toString().padStart(2, '0');
  const hours = d.getHours().toString().padStart(2, '0');
  const minutes = d.getMinutes().toString().padStart(2, '0');
  const seconds = d.getSeconds().toString().padStart(2, '0');
  
  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('HH', hours)
    .replace('mm', minutes)
    .replace('ss', seconds);
}

/**
 * 获取当前日期的格式化字符串
 * @param {string} format - 格式化模板
 * @return {string} 格式化后的日期字符串
 */
function getNow(format = 'YYYY-MM-DD') {
  return formatDate(new Date(), format);
}

/**
 * 获取中文格式的日期
 * @param {Date|number|string} date - 日期对象、时间戳或日期字符串，默认为当前日期
 * @return {string} 格式为"YYYY年MM月"的日期字符串
 */
function fmtDateCN(date) {
  const d = date ? new Date(date) : new Date();
  const year = d.getFullYear();
  const month = d.getMonth() + 1;
  return `${year}年${month}月`;
}

/**
 * 格式化时间，支持多种格式标记
 * @param {string} format - 格式模板：Y年, M月, D日, h时, m分, s秒
 * @param {Date|number|string} [t] - 时间对象，默认为当前时间
 * @returns {string} 格式化后的时间字符串
 */
function time(format, t) {
  // 使用当前时间作为默认值
  const date = t ? new Date(t) : new Date();
  
  // 年
  let Y = date.getFullYear();
  // 月，从0开始需要+1
  let M = date.getMonth() + 1;
  // 日
  let D = date.getDate();
  // 时
  let h = date.getHours();
  // 分
  let m = date.getMinutes();
  // 秒
  let s = date.getSeconds();
  
  // 补0操作
  if (M < 10) M = '0' + M;
  if (D < 10) D = '0' + D;
  if (h < 10) h = '0' + h;
  if (m < 10) m = '0' + m;
  if (s < 10) s = '0' + s;
  
  // 根据format格式进行替换
  return format
    .replace('Y', Y)
    .replace('M', M)
    .replace('D', D)
    .replace('h', h)
    .replace('m', m)
    .replace('s', s);
}

/**
 * 计算未来日期
 * @param {number} days - 天数
 * @param {Date|number|string} date - 基准日期，默认今天
 * @param {string} format - 返回格式
 * @return {string} 计算后的日期字符串
 */
function addDays(days, date, format = 'YYYY-MM-DD') {
  const baseDate = date ? new Date(date) : new Date();
  baseDate.setDate(baseDate.getDate() + days);
  return formatDate(baseDate, format);
}

/**
 * 计算未来月份
 * @param {number} months - 月数
 * @param {Date|number|string} date - 基准日期，默认今天
 * @param {string} format - 返回格式
 * @return {string} 计算后的日期字符串
 */
function addMonths(months, date, format = 'YYYY-MM-DD') {
  const baseDate = date ? new Date(date) : new Date();
  baseDate.setMonth(baseDate.getMonth() + months);
  return formatDate(baseDate, format);
}

/**
 * 时间戳转日期字符串
 * @param {number} timestamp - 秒级时间戳
 * @param {string} format - 返回格式
 * @return {string} 计算后的日期字符串
 */
function timestampToDate(timestamp, format = 'YYYY-MM-DD') {
  // 转为毫秒级时间戳
  const millTimestamp = String(timestamp).length === 10 
    ? timestamp * 1000 
    : Number(timestamp);
  
  return formatDate(new Date(millTimestamp), format);
}

/**
 * 日期字符串转时间戳
 * @param {string} dateStr - 日期字符串
 * @param {boolean} isSecond - 是否返回秒级时间戳
 * @return {number} 时间戳
 */
function dateToTimestamp(dateStr, isSecond = true) {
  const date = new Date(dateStr.replace(/-/g, '/'));
  return isSecond ? Math.floor(date.getTime() / 1000) : date.getTime();
}

/**
 * 获取两个日期之间的天数
 * @param {Date|number|string} startDate - 开始日期
 * @param {Date|number|string} endDate - 结束日期
 * @return {number} 相差的天数
 */
function getDaysBetween(startDate, endDate) {
  const start = new Date(startDate);
  const end = new Date(endDate);
  start.setHours(0, 0, 0, 0);
  end.setHours(0, 0, 0, 0);
  
  const diffTime = Math.abs(end - start);
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}

/**
 * 判断日期大小
 * @param {Date|number|string} date1 - 日期1
 * @param {Date|number|string} date2 - 日期2
 * @return {number} 1:date1>date2, -1:date1<date2, 0:相等
 */
function compareDate(date1, date2) {
  const d1 = new Date(date1);
  const d2 = new Date(date2);
  
  if (d1.getTime() > d2.getTime()) return 1;
  if (d1.getTime() < d2.getTime()) return -1;
  return 0;
}

/**
 * 获取相对时间描述
 * @param {Date|number|string} date - 日期
 * @return {string} 相对时间描述文本
 */
function getRelativeTime(date) {
  const now = new Date();
  const targetDate = new Date(date);
  const diffSeconds = Math.floor((now - targetDate) / 1000);
  
  if (diffSeconds < 60) return '刚刚';
  if (diffSeconds < 3600) return `${Math.floor(diffSeconds / 60)}分钟前`;
  if (diffSeconds < 86400) return `${Math.floor(diffSeconds / 3600)}小时前`;
  if (diffSeconds < 2592000) return `${Math.floor(diffSeconds / 86400)}天前`;
  
  return formatDate(targetDate);
}

/**
 * 获取基于时间的唯一ID
 * @returns {string} 格式为YYYYMMDDHHmmss+随机数的字符串
 */
function getTimeID() {
  const date = new Date();
  const year = date.getFullYear().toString();
  const month = (date.getMonth() + 1).toString().padStart(2, '0');
  const day = date.getDate().toString().padStart(2, '0');
  const hour = date.getHours().toString().padStart(2, '0');
  const minute = date.getMinutes().toString().padStart(2, '0');
  const second = date.getSeconds().toString().padStart(2, '0');
  const random = Math.floor(Math.random() * 100000).toString().padStart(5, '0');
  
  return year + month + day + hour + minute + second + random;
}

/**
 * 时间戳转时间字符串
 * @param {number} timestamp - 时间戳（秒）
 * @param {string} fmt - 格式模板
 * @returns {string} 格式化的时间字符串
 */
function timestamp2Time(timestamp, fmt = 'YYYY-MM-DD HH:mm:ss') {
  if (!timestamp) return '';
  return timestampToDate(timestamp, fmt);
}

/**
 * 时间戳转日期字符串
 * @param {number} timestamp - 时间戳（秒）
 * @param {string} fmt - 格式模板
 * @returns {string} 格式化的日期字符串
 */
function timestamp2Date(timestamp, fmt = 'YYYY-MM-DD') {
  return timestamp2Time(timestamp, fmt);
}

/**
 * 将日期字符串转为时间戳
 * @param {string} dateStr - 日期字符串
 * @returns {number} 时间戳（秒）
 */
function time2Timestamp(dateStr) {
  return dateToTimestamp(dateStr);
}

// 导出方法
module.exports = {
  formatDate,
  getNow,
  fmtDateCN,
  time,
  addDays,
  addMonths,
  timestampToDate,
  dateToTimestamp,
  getDaysBetween,
  compareDate,
  getRelativeTime,
  getTimeID,
  
  // 兼容命名
  timestamp2Time,
  timestamp2Date,
  time2Timestamp
};